﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Syndication;
using FeedsLibrary.DataBaseModel;


namespace FeedsLibrary
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class FeedsService : IFeedsService
    {
        #region Fields
        RssReader.RssReader rssreader = new RssReader.RssReader();
        ServerIIDataBaseModelContainer db = new ServerIIDataBaseModelContainer();
        #endregion

        public bool IsParamsNull(List<string> parameters)
        {
            foreach (String str in parameters)
            {
                if (String.IsNullOrWhiteSpace(str)) return true;
            }
            return false;
        }

        public Dictionary<string, string> GetAllParentFeeds(string email)
        {
            if(IsParamsNull(new List<string> {email})) return (null);
            var u = (from user in db.UserVsParentFeeds where user.User.Email == email select user.User).ToList();
            if (u.Count() == 0) return (null);
            Dictionary<string, string> titlevslink = new Dictionary<string, string>();
            Dictionary<string, string> titlevscategory = new Dictionary<string, string>();

            titlevslink = rssreader.GetAllSavedParentFeeds(titlevscategory);
            try
            {
                foreach (KeyValuePair<string, string> k in titlevscategory)
                {
                    ParentFeed p = new ParentFeed();
                    p.Title = k.Key; p.Category = k.Value;
                    foreach (KeyValuePair<string, string> kl in titlevslink)
                    {
                        if (kl.Key == p.Title) p.Link = kl.Value;
                    }
                    UserVsParentFeed uservsparentfeed = new UserVsParentFeed();
                    uservsparentfeed.ParentFeed = p;
                    uservsparentfeed.User = u[0];
                    db.UserVsParentFeeds.AddObject(uservsparentfeed);
                    db.SaveChanges();
                }
            }
            catch { }
            return (titlevslink);
        }

        public bool AddNewParentFeed(string email, string parentfeedurl, string category)
        {
            if (IsParamsNull(new List<string> { email, parentfeedurl, category})) return false;
            var u = (from user in db.UserVsParentFeeds where user.User.Email == email select user.User).ToList();
            if (u.Count() == 0) return false;
            Dictionary<string, string> infos = new Dictionary<string, string>();
            infos = rssreader.GetParentFeedInfos(parentfeedurl, category);
            bool res = true;
            try
            {
                ParentFeed p = new ParentFeed();
                p.Title = infos["TITLE"];
                p.Link = infos["LINK"];
                p.Lastupdatedate = infos["LAST UPDATE DATE"];
                p.Category = category;
                p.Description = infos["DESCRIPTION"];
                p.Author = infos["AUTHOR"];
                UserVsParentFeed uservsparentfeed = new UserVsParentFeed();
                uservsparentfeed.ParentFeed = p;
                uservsparentfeed.User = u[0];
                db.UserVsParentFeeds.AddObject(uservsparentfeed);
                db.SaveChanges();
            }
            catch { res = false; }
            return res;
        }

        public Dictionary<string, string> GetParentFeedInfos(string parentfeedurl, string category = "VARIOUS")
        {
            Dictionary<string, string> infos = new Dictionary<string, string>();

            try
            {
                infos = rssreader.GetParentFeedInfos(parentfeedurl, category);
            }
            catch { infos = new Dictionary<string, string>(); }
            return infos;
        }

        public List<Dictionary<string, string>> GetMyChildFeeds(string email, string category = "ALL")
        {
            if (IsParamsNull(new List<string> { email })) return (null);
            var res = (from parents in db.UserVsParentFeeds where parents.User.Email == email  &&
                       parents.ParentFeed.Category == category select parents.ParentFeed).ToList();
            if (res.Count() == 0) return (null);
            List<Dictionary<string, string>> infos = new List<Dictionary<string, string>>();
            try
            {
                foreach (ParentFeed p in res)
                {
                    foreach (ChildFeed c in p.ChildFeeds)
                    {
                        Dictionary<string, string> childinfos = new Dictionary<string, string>();
                        childinfos.Add("TITLE", c.Title);
                        childinfos.Add("LINKS", c.Title);
                        childinfos.Add("AUTHOR", c.Title);
                        childinfos.Add("PUBLISH DATE", c.Title);
                        childinfos.Add("LAST UPDATE DATE", c.Title);
                        childinfos.Add("CATEGORY", c.Title);
                        childinfos.Add("SUMMARY", c.Title);
                        infos.Add(childinfos);
                    }
                }
            }
            catch { }
            return (infos);
        }

        public List<Dictionary<string, string>> GetMySharedFeeds(string email, string category = "ALL")
        {
            if (IsParamsNull(new List<string> { email })) return (null);
            var res = (from parents in db.UserVsParentFeeds where parents.ParentFeed.Category == category &&
                           parents.User.Email == email select parents.ParentFeed).ToList();
            if (res.Count() == 0) return (null);
            List<Dictionary<string, string>> infos = new List<Dictionary<string, string>>();
            foreach(ParentFeed p in res)
            {
                foreach (ChildFeed c in p.ChildFeeds)
                {
                    if (c.Shared == true)
                    {
                        Dictionary<string, string> childindfos = new Dictionary<string, string>();
                        childindfos.Add("TITLE", c.Title); childindfos.Add("LINK", c.Link);
                        childindfos.Add("LAST UPDATE DATE", c.Lastupdatedate);
                        childindfos.Add("CATEGORY", c.Category); childindfos.Add("SUMMARY", c.Summary);
                        childindfos.Add("AUTHOR", c.Author); childindfos.Add("PUBLISH DATE", c.Pubdate);
                        infos.Add(childindfos);
                    }
                }
            }
            return (infos);
        }

        public bool IsFeedRead(string email, string fieldtitle, string category = "UNKNOWN")
        {
            if (IsParamsNull(new List<string> { email })) return (false);
            var res = (from parents in db.UserVsParentFeeds where parents.User.Email == email &&
                       parents.ParentFeed.Category == category select parents.ParentFeed).ToList();
            if (res.Count() == 0) return (false);
            var result = (from childfield in res[0].ChildFeeds where childfield.Title == fieldtitle select childfield.State).ToList();
            if (result.Count() == 0) return (false);
            bool ret = (result[0] == "READ") ? (true) : (false);
            return (ret);
        }

        public bool SetFeedState(string email, string fieldtitle, string category = "UNKNOWN")
        {
            if (IsParamsNull(new List<string> { email })) return (false);
            var res = (from parents in db.UserVsParentFeeds where parents.ParentFeed.Category == category
                       && parents.User.Email == email select parents.ParentFeed).ToList();
            if (res.Count() == 0) return (false);
            var result = (from childfield in res[0].ChildFeeds where childfield.Title == fieldtitle select childfield).ToList();
            if (result.Count() == 0) return (false);
            bool ret = true;
            try
            {
                result[0].State = "READ";
                db.SaveChanges();
            }
            catch { ret = false; }
            return (ret);
        }

        public bool ShareFeed(string email, string fieldtitle, string category = "UNKNOWN")
        {
            if (IsParamsNull(new List<string> { email })) return (false);
            var u = (from user in db.UserVsParentFeeds where user.User.Email == email select user.User).ToList();
            if (u.Count() == 0) return (false);

            var res = (from parents in db.UserVsParentFeeds where parents.User.Email == email  && parents.ParentFeed.Category == category select parents.ParentFeed).ToList();
            if (res.Count() == 0) return (false);
            var result = (from childfield in res[0].ChildFeeds where childfield.Title == fieldtitle select childfield).ToList();
            if (result.Count() == 0) return (false);
            bool ret = true;
            try
            {
                result[0].Shared = true;
                db.SaveChanges();
            }
            catch { ret = false; }
            return (ret);
        }

        public bool ShareFeedList(string email, List<string> fieldtitles, string category = "UNKNOWN")
        {
            bool res = false;
            foreach (string s in fieldtitles)
            {
                res = ShareFeed(email, s, category);
            }
            return(res);
        }

        public bool RemoveChildField(string email, string fieldtitle, string category = "UNKNOWN")
        {
            bool ret = true;
            if (IsParamsNull(new List<string> { email })) return (false);
            var u = (from user in db.UserVsParentFeeds where user.User.Email == email select user.User).ToList();
            if (u.Count() == 0) return (false);

            var res = (from parents in db.UserVsParentFeeds where parents.User.Email == email && parents.ParentFeed.Category == category select parents.ParentFeed).ToList();
            if (res.Count() == 0) return (false);
            var result = (from childfield in res[0].ChildFeeds where childfield.Title == fieldtitle select childfield).ToList();
            if (result.Count() == 0) return (false);
            try
            {
                res[0].ChildFeeds.Remove(result[0]);
            }
            catch { ret = false; }
            return (ret);
        }

        public bool RefreshParentChildFeeds(string email, string parentfeedurl)
        {
            bool ret = true;
            Predicate<List<ParentFeed>> isempty = x => x.Count == 0;
            var res = (from parents in db.UserVsParentFeeds where parents.User.Email == email select parents.ParentFeed).ToList();
            if (isempty.Invoke(res) == true) return false;
            List<Dictionary<string, string>> children = new List<Dictionary<string, string>>();
            children = rssreader.SubscribeToFeed(parentfeedurl);
            foreach (Dictionary<string, string> d in children)
            {
                Predicate<List<ChildFeed>> childisempty = x => x.Count != 0;
                var c = (from child in res[0].ChildFeeds where child.Title == d["TITLE"] select child).ToList();
                if (childisempty.Invoke(c) == true) children.Remove(d); 
            }
            foreach (Dictionary<string, string> d in children)
            {
                ChildFeed c = new ChildFeed();
                c.Title = d["TITLE"]; c.Link = d["LINKS"];
                c.Author = d["AUTHOR"]; c.Pubdate = d["PUBLISH DATE"];
                c.Lastupdatedate = d["LAST UPDATE DATE"];
                c.Category = d["CATEGORY"]; c.Summary = d["SUMMARY"];
                c.State = "UNREAD";
                c.Owner = email;
                c.Shared = false;
                c.Guest = "ADMIN";
                try
                {
                    res[0].ChildFeeds.Add(c);
                    db.SaveChanges();
                }
                catch { ret = false; }
            }
            return(ret);
        }

        public List<Dictionary<string, string>> SubscribeToFeed(string email, string parentfeedurl, string category = "VARIOUS")
        {
            Predicate<List<ParentFeed>> isempty = x => x.Count == 0;
            var res = (from parents in db.UserVsParentFeeds
                        where parents.User.Email == email &&
                        parents.ParentFeed.Link == parentfeedurl && parents.ParentFeed.Category == category
                       select parents.ParentFeed).ToList();
            if (isempty.Invoke(res) == true) return null;
            List<Dictionary<string, string>> children = new List<Dictionary<string, string>>();
            children = rssreader.SubscribeToFeed(parentfeedurl);
            foreach (Dictionary<string, string> d in children)
            {
                ChildFeed c = new ChildFeed();
                c.Title = d["TITLE"]; c.Link = d["LINKS"];
                c.Author = d["AUTHOR"]; c.Pubdate = d["PUBLISH DATE"];
                c.Lastupdatedate = d["LAST UPDATE DATE"];
                c.Category = d["CATEGORY"]; c.Summary = d["SUMMARY"];
                c.State = "UNREAD";
                c.Owner = email;
                c.Shared = false;
                c.Guest = "ADMIN";
                try
                {
                    res[0].ChildFeeds.Add(c);
                    db.SaveChanges();
                }
                catch {  }
            }
            return (children);
        }
    }
}
